home *** CD-ROM | disk | FTP | other *** search
Wrap
/* File: godmode.c Copyright (C) 1998-2004 Christophe GRENIER <grenier@cgsecurity.org> This software is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define DEBUG 1 #include <ctype.h> /* toupper, tolower */ #include <stdlib.h> #include <string.h> #include "types.h" #include "common.h" #include "fnctdsk.h" #include "analyse.h" #include "lang.h" #include "godmode.h" #include "testdisk.h" #include "fat.h" #include "ext2.h" #include "intrface.h" #include "md.h" #include "adv.h" #define RO 1 #define RW 0 static void align_structure(const t_param_disk *disk_car, t_list_part *list_part); static void init_structure(const t_param_disk *disk_car,t_list_part *list_part, const int debug); static void init_part_order(t_list_part *list_part); static void ask_mbr_order(t_param_disk *disk_car,t_list_part *list_part); static t_list_part *reduce_structure(t_list_part *list_part); static t_list_part *add_ext_part(t_param_disk *disk_car, t_list_part *list_part, const int max_ext); static int write_mbr(t_param_disk *disk_car, const t_list_part *list_part, const int ro, const int debug); static int write_all_log(t_param_disk *disk_car, const t_list_part *list_part, const int ro , const int debug); static int diff(const unsigned char buffer[SECTOR_SIZE], const unsigned char buffer_org[SECTOR_SIZE]); static t_list_part *do_recover_cih(t_param_disk *disk_car,t_list_part *list_part,int debug, const int dump_ind); static int use_backup(t_param_disk *disk_car, const t_list_part *list_part, const int debug,const int dump_ind); static void align_structure(const t_param_disk *disk_car, t_list_part *list_part) { t_list_part *element; for(element=list_part;element!=NULL;element=element->next) { t_CHS end; LBA2CHS(disk_car,element->part->lba+element->part->part_size-1,&end); end.sector=disk_car->CHS.sector; end.head=disk_car->CHS.head; element->part->part_size=CHS2LBA(disk_car, &end)-element->part->lba+1; } } static void init_structure(const t_param_disk *disk_car,t_list_part *list_part, const int debug) { /* Reconstruit une structure * nbr_prim nombre de partition primaire * end_log_block : partition etendu du block etendu * nbr_log_block : nombre de block de partition etendu * devrait etre 0 ou 1 */ unsigned int nbr_prim=0, nbr_log_block=0; t_list_part *element; t_list_part *end_log_block=NULL; t_list_part *end_biggest_log_block=NULL; unsigned int log_block_size=0,biggest_log_block_size=0; t_list_part *new_list_part=NULL; /* Create new list */ for(element=list_part;element!=NULL;element=element->next) element->to_be_removed=0; for(element=list_part;element!=NULL;element=element->next) { int to_be_removed=0; t_list_part *element2; for(element2=element->next;element2!=NULL;element2=element2->next) if(element->part->lba+element->part->part_size-1 >= element2->part->lba) { to_be_removed=1; element2->to_be_removed=1; } if(to_be_removed) element->to_be_removed=1; if(element->to_be_removed==0) new_list_part=insert_new_partition(new_list_part,element->part); } /* Verify */ for(element=new_list_part;element!=NULL;element=element->next) { if(can_be_ext(disk_car,element->part)==0) { nbr_prim++; if((end_log_block!=NULL) && (end_log_block->next==element)) { if(log_block_size>biggest_log_block_size) { biggest_log_block_size=log_block_size; end_biggest_log_block=end_log_block; } nbr_log_block++; end_log_block=NULL; } } else { log_block_size++; end_log_block=element; } } /* Verification */ if((end_log_block!=NULL) && (end_log_block->next==NULL)) { if(log_block_size>biggest_log_block_size) { biggest_log_block_size=log_block_size; end_biggest_log_block=end_log_block; } nbr_log_block++; } if(debug>1) ecrit_rapport("\nRes: nbr_prim %u, nbr_log_block %u\n", nbr_prim, nbr_log_block); /* Set primary, extended, logical */ if(nbr_prim+nbr_log_block<=4) { int set_prim_bootable_done=0; for(element=end_biggest_log_block;element&&can_be_ext(disk_car,element->part);element=element->prev) { /* ecrit_rapport("%p %p %p %d\n",element,element->prev,element->next,element->part->status); */ element->part->status=STATUS_LOG; } for(element=new_list_part;element!=NULL;element=element->next) { if(element->part->status!=STATUS_LOG) { if(set_prim_bootable_done) element->part->status=STATUS_PRIM; else { /* The first primary partition is bootable unless it's a swap */ if(element->part->upart_type!=UP_LINSWAP) { element->part->status=STATUS_PRIM_BOOT; set_prim_bootable_done=1; } } } } } check_list_part(new_list_part); if(test_structure(new_list_part)) { for(element=new_list_part;element!=NULL;element=element->next) element->part->status=STATUS_DELETED; } { /* free */ t_list_part *new_element; for(element=new_list_part;element!=NULL;element=new_element) { new_element=element->next; FREE(element); } } check_list_part(list_part); } void only_one_bootable( t_list_part *list_part, t_list_part *part_boot) { t_list_part *element; if(part_boot->part->status==STATUS_PRIM_BOOT) for(element=list_part;element!=NULL;element=element->next) { if((element!=part_boot)&&(element->part->status==STATUS_PRIM_BOOT)) element->part->status=STATUS_PRIM; } } t_list_part *search_part(t_param_disk *disk_car, const int paranoid, const int debug, const int dump_ind, const int fast_mode,const int interface) { int ind_stop=FALSE; t_CHS start; t_list_part *list_part=NULL; t_diskext *partition=partition_new(); if(interface!=0) { wmove(stdscr,22,0); wstandout(stdscr); waddstr(stdscr," Stop "); wstandend(stdscr); } aff_buffer(BUFFER_RESET,"Q"); ecrit_rapport("\nsearch_part()\n"); ecrit_rapport("%s",disk_car->description(disk_car)); /* ncurses: getch will be a non-blocking call */ for(start.cylinder=0,start.head=1;(start.cylinder<=disk_car->CHS.cylinder)&&(ind_stop==0);start.cylinder++,start.head=0) { if(interface!=0) { wmove(stdscr,ANALYSE_Y,ANALYSE_X); wclrtoeol(stdscr); wdoprintf(stdscr,"Analyse cylinder %5u/%u",start.cylinder,disk_car->CHS.cylinder); wrefresh(stdscr); switch(wgetch_nodelay(stdscr)) { case KEY_ENTER: #ifdef PADENTER case PADENTER: #endif case '\n': case '\r': case 's': case 'S': ind_stop=1; break; } } for(;(start.head<=disk_car->CHS.head);start.head++) { unsigned int sector_inc; int part_offset; for(start.sector=1,sector_inc=1,part_offset=0;(start.sector<=disk_car->CHS.sector);start.sector+=sector_inc) { int res=0; partition_reset(partition); /* must not reset lba */ partition->lba=CHS2LBA(disk_car,&start); if((start.sector==1) && ((start.head<=2)||(fast_mode==2))) { part_offset++; switch(part_offset) { case 1: res=search_type_128(disk_car,partition,debug,dump_ind); sector_inc=0; break; case 2: res=search_type_2(disk_car,partition,debug,dump_ind); break; case 3: res=search_type_1(disk_car,partition,debug,dump_ind); break; case 4: res=search_type_0(disk_car,partition,debug,dump_ind); sector_inc=1; break; default: ecrit_rapport("\nBUG: unusual value of part_offset\n"); break; } } else if(start.sector==7 && fast_mode>0 && ((start.head<=2)||(fast_mode==2))) { res=search_FAT_backup(disk_car,partition,debug,dump_ind); } else if(start.sector==disk_car->CHS.sector && fast_mode>0) { if((start.head==disk_car->CHS.head)||(fast_mode>1)) { res=search_NTFS_backup(disk_car,partition,debug,dump_ind); } } if(res<0) { if(interface!=0) { wdoprintf(stdscr,msg_READ_ERROR_AT, start.cylinder,start.head,start.sector,partition->lba); } } if(res<=0 && paranoid!=0) { int s_log_block_size; dword ref_lba=partition->lba; /* try backup superblock */ /* It must be in paranoid mode because it can hide otherwise other partition type */ /* Block size: 1024, 2048 or 4096 bytes (8192 bytes on Alpha systems) */ /* From e2fsprogs-1.34/lib/ext2fs/initialize.c: set_field(s_first_data_block, super->s_log_block_size ? 0 : 1); */ /* Assumes that TestDisk is not running under Alpha and s_blocks_per_group=8 * block size */ for(s_log_block_size=0;(s_log_block_size<=2)&&(res<1);s_log_block_size++) { /* sparse superblock feature: The groups chosen are 0, 1 and powers of 3, 5 and 7. */ /* Checking group 3 */ const dword hd_offset=3*(EXT2_MIN_BLOCK<<s_log_block_size)*8*(EXT2_MIN_BLOCK_SIZE<<s_log_block_size)+(s_log_block_size==0?2:0); if(ref_lba>(3*(EXT2_MIN_BLOCK<<s_log_block_size)*8*(EXT2_MIN_BLOCK_SIZE<<s_log_block_size)) && LBA2sector(disk_car,ref_lba-hd_offset)==1 && (LBA2head(disk_car,ref_lba-hd_offset)<=2 || fast_mode==2)) { unsigned char buffer[2*SECTOR_SIZE]; /* unsigned int block_size=(EXT2_MIN_BLOCK_SIZE<<s_log_block_size); */ /* ecrit_rapport("CHS %u/%u/%u %lu %u res=%d\n",start.cylinder,start.head,start.sector,partition->lba,part_offset,res); */ /* ecrit_rapport("Block size=%u Group %u Backup superblock at %u ?\n",EXT2_MIN_BLOCK_SIZE<<s_log_block_size,group,group*s_blocks_per_group); */ if(disk_car->read(disk_car,2, &buffer, ref_lba)==0) { const struct ext2_super_block *sb=(const struct ext2_super_block*)&buffer; if(le16(sb->s_block_group_nr)>0) { if(recover_EXT2(disk_car,sb,partition,debug,dump_ind)==0) res=1; } } else { res=-1; } } } } if(res<=0 && fast_mode>1) { /* Because this superblock is at the end of the partition, you should be * in slow mode to find it... */ unsigned char buffer[8*SECTOR_SIZE]; if(disk_car->read(disk_car,8, &buffer, partition->lba)!=0) { res=-1; } else { if(recover_MD(disk_car,(const struct mdp_superblock_s*)&buffer,partition,debug,dump_ind)==0) res=1; else res=0; } } if(res>0) { if(partition->part_type!=0 && is_extended(partition->part_type)==0 && partition->part_size>1 && partition->lba>0) { dword pos_fin=partition->lba+partition->part_size-1; aff_part_rapport(disk_car,partition); if(pos_fin<=disk_car->size) { t_diskext *new_partition=partition_new(); dup_t_diskext(new_partition,partition); new_partition->status=STATUS_DELETED; /* check_part(disk_car,debug,new_partition); */ aff_part_buffer(AFF_PART_NL,disk_car,new_partition); list_part=insert_new_partition(list_part,new_partition); if(interface) { aff_buffer(BUFFER_SHOW,"Q"); } if((paranoid==0) && (partition->lba+partition->part_size-1> CHS2LBA(disk_car,&start))) { LBA2CHS(disk_car,partition->lba+partition->part_size-1,&start); part_offset=0; sector_inc=1; } } else { if(debug>0) { aff_part_rapport(disk_car,partition); if(pos_fin>disk_car->size) { ecrit_rapport("This partition ends after the disk limits. "); } ecrit_rapport("(start=%lu, size=%lu, end=%lu, disk end=%lu)\n", partition->lba,partition->part_size, pos_fin,disk_car->size); } } } } } } } FREE(partition); return list_part; } static void init_part_order(t_list_part *list_part) { int nbr_log=0; int nbr_prim=0; t_list_part *element; for(element=list_part;element!=NULL;element=element->next) { switch(element->part->status) { case STATUS_PRIM: case STATUS_PRIM_BOOT: case STATUS_EXT: element->part->order=++nbr_prim; break; case STATUS_LOG: element->part->order=(++nbr_log)+4; break; default: ecrit_rapport("init_part_order: severe error\n"); break; } } } static void ask_mbr_order(t_param_disk *disk_car,t_list_part *list_part) { t_diskext *table[4]; t_diskext *table2[4]; int nbr_prim=0; int i,pos=0; int res; int car; int quit=0; t_list_part *element; /* Initialisation */ aff_copy(stdscr); wmove(stdscr,4,0); wdoprintf(stdscr,"%s",disk_car->description(disk_car)); mvwaddstr(stdscr,5,0,msg_MBR_ORDER); mvwaddstr(stdscr,6,0,msg_PART_HEADER2); for(element=list_part;element!=NULL;element=element->next) { if((element->part->order>0) && (element->part->order<5)) table[nbr_prim++]=element->part; } /* */ ecrit_rapport("\nSelection des partitions primaires\n"); for(i=0;i<nbr_prim;i++) aff_part_rapport(disk_car,table[i]); /* */ do { unsigned int order; /* sort table into table2 */ int part=0; res=0; for(order=1;order<=4;order++) { int nbr=0; for(i=0;i<nbr_prim;i++) if(table[i]->order==order) { table2[part++]=table[i]; nbr++; } res|=(nbr>1); } if(part!=nbr_prim) { ecrit_rapport("\nBUG part %d, nbr_prim %d\n", part, nbr_prim); } /* */ for(i=0;i<nbr_prim;i++) { wmove(stdscr,5+2+i,0); wclrtoeol(stdscr); if(i==pos) standout(); aff_part(stdscr,AFF_PART_ORDER,disk_car,table2[i]); if(i==pos) standend(); } wmove(stdscr,20,0); if(res) wdoprintf(stdscr,msg_MBR_ORDER_BAD); else wdoprintf(stdscr,msg_MBR_ORDER_GOOD); wrefresh(stdscr); car=wgetch(stdscr); quit=0; switch(car) { case KEY_UP: if(--pos<0) pos=nbr_prim-1; break; case KEY_DOWN: if(++pos>=nbr_prim) pos=0; break; case KEY_PPAGE: pos=0; break; case KEY_NPAGE: pos=nbr_prim-1; break; case '1': case '2': case '3': case '4': table2[pos]->order=car-'0'; break; case KEY_RIGHT: case ' ': case '+': if(++table2[pos]->order>4) table2[pos]->order=1; break; case KEY_LEFT: case '-': if(--table2[pos]->order<1) table2[pos]->order=4; break; case 'q': case '\r': case '\n': case KEY_ENTER: #ifdef PADENTER case PADENTER: #endif case 'M': quit=1; break; } wrefresh(stdscr); } while(res!=0 || quit==0); } static t_list_part *reduce_structure(t_list_part *list_part) { t_list_part *element=list_part; t_list_part *prev=NULL; while(element) { t_list_part *next=element->next; if(element->part->status==STATUS_DELETED) { if(prev==NULL) list_part=next; else prev->next=next; if(next!=NULL) next->prev=prev; FREE(element->part); FREE(element); } else prev=element; element=next; } return list_part; } static t_list_part *add_ext_part(t_param_disk *disk_car, t_list_part *list_part, const int max_ext) { /* list_part need to be sorted! */ /* All extended partitions of an P_EXTENDX are P_EXTENDED */ t_list_part *element; t_list_part *deb=NULL; t_list_part *fin=NULL; int nbr_entries=0; t_CHS start,end; t_diskext *new_partition; for(element=list_part;element!=NULL;element=element->next) { if(element->part->status==STATUS_LOG) { if(deb==NULL) { deb=element; nbr_entries++; } fin=element; } else nbr_entries++; } if(deb==NULL) return list_part; start.sector=1; if((nbr_entries==4)||(max_ext!=0)) { start.cylinder=(deb->prev==NULL?1:LBA2cylinder(disk_car,deb->prev->part->lba+deb->prev->part->part_size-1)+1); start.head=0; end.cylinder=(fin->next==NULL?disk_car->CHS.cylinder:LBA2cylinder(disk_car,fin->next->part->lba)-1); /* 8 october 2002 */ end.head=disk_car->CHS.head; end.sector=disk_car->CHS.sector; } else { start.cylinder=LBA2cylinder(disk_car,deb->part->lba); if(LBA2head(disk_car,deb->part->lba)==0) ecrit_rapport("BUG while creating a minimal extended partition\n"); start.head=LBA2head(disk_car,deb->part->lba)-1; end.cylinder=LBA2cylinder(disk_car,fin->part->lba+fin->part->part_size-1); end.head=disk_car->CHS.head; end.sector=disk_car->CHS.sector; } new_partition=partition_new(); new_partition->part_type=(end.cylinder>1023?P_EXTENDX:P_EXTENDED); new_partition->status=STATUS_EXT; new_partition->lba=CHS2LBA(disk_car,&start); new_partition->part_size=CHS2LBA(disk_car,&end)-new_partition->lba+1; return insert_new_partition(list_part, new_partition); } static int write_mbr(t_param_disk *disk_car, const t_list_part *list_part, const int ro, const int debug) { const t_list_part *element; unsigned char buffer[SECTOR_SIZE]; unsigned char buffer_org[SECTOR_SIZE]; if(debug) ecrit_rapport("\nwrite_mbr: starting...\n"); if(read_MBR(disk_car,&buffer_org)) return 1; memset((void *)&buffer,0,SECTOR_SIZE); if((buffer_org[0x1FE]==0x55) && (buffer_org[0x1FF]==0xAA)) { memcpy(buffer,buffer_org,TAB_PART); buffer[0x1FE]=0x55; buffer[0x1FF]=0xAA; } else { write_MBR_code_aux(buffer); } for(element=list_part;element!=NULL;element=element->next) { switch(element->part->status) { case STATUS_PRIM: case STATUS_PRIM_BOOT: case STATUS_EXT: if((element->part->order>=1) && (element->part->order<=4)) { partition2entry(disk_car,0,element->part, pt_offset(buffer,element->part->order-1)); } break; case STATUS_LOG: break; default: ecrit_rapport("write_mbr: severe error\n"); break; } } if(debug>1) { int i; for(i=0;i<4;i++) { const struct partition_dos *p=pt_offset(buffer,i); aff_entry_rapport(p); } diff(buffer,buffer_org); } if(ro==0) return write_MBR(disk_car,&buffer); return 0; } static int diff(const unsigned char buffer[SECTOR_SIZE], const unsigned char buffer_org[SECTOR_SIZE]) { int j; if(memcmp(buffer,buffer_org,SECTOR_SIZE)) { ecrit_rapport("\nSectors are different.\n"); ecrit_rapport("buffer_org\n"); for(j=0;j<4;j++) { const struct partition_dos *p=pt_offset_const(buffer_org,j); if(p->sys_ind!=0) aff_entry_rapport(p); } ecrit_rapport("buffer\n"); for(j=0;j<4;j++) { const struct partition_dos *p=pt_offset_const(buffer,j); if(p->sys_ind!=0) aff_entry_rapport(p); } for(j=0;j<SECTOR_SIZE;j++) if(buffer_org[j]!=buffer[j]) ecrit_rapport("%02X %02X %02X\n", j, buffer_org[j], buffer[j]); ecrit_rapport("\n"); } return 0; } static int use_backup(t_param_disk *disk_car, const t_list_part *list_part, const int debug,const int dump_ind) { const t_list_part *element; ecrit_rapport("use_backup\n"); for(element=list_part;element!=NULL;element=element->next) { if(element->part->boot_sector!=0) { switch(element->part->upart_type) { case UP_FAT32: fat32_boot_sector(disk_car, element->part, debug, dump_ind); break; case UP_NTFS: ntfs_boot_sector(disk_car, element->part, debug, dump_ind); break; default: ecrit_rapport("Need to fix\n"); aff_part_rapport(disk_car,element->part); break; } } } return 0; } static int write_all_log(t_param_disk *disk_car, const t_list_part *list_part, const int ro, const int debug) { const t_list_part *element; const t_list_part *pos_ext=NULL; dword current_pos; t_diskext *bloc_nextext; if(debug) ecrit_rapport("write_all_log: starting...\n"); for(element=list_part;element!=NULL;element=element->next) { if(element->part->status==STATUS_EXT) { if(is_extended(element->part->part_type)) { if(pos_ext!=NULL) ecrit_rapport("write_all_log: pos_ext already defined\n"); pos_ext=element; } else { ecrit_rapport("write_all_log: STATUS_EXT with bad part_type\n"); } } } if(pos_ext==NULL) { wdoprintf(stdscr,msg_NO_EXT_PART); return 1; } current_pos=pos_ext->part->lba; bloc_nextext=(t_diskext *)MALLOC(sizeof(*bloc_nextext)); bloc_nextext->part_type=P_EXTENDED; /* Never P_EXTENDX */ if(pos_ext->next==NULL || (pos_ext->next->part->status!=STATUS_LOG)) { unsigned char buffer[SECTOR_SIZE]; unsigned char buffer_org[SECTOR_SIZE]; if(debug) { ecrit_rapport("write_all_log: CHS: %u/%u/%u,lba=%lu\n", LBA2cylinder(disk_car,current_pos), LBA2head(disk_car,current_pos), LBA2sector(disk_car,current_pos),current_pos); } if(disk_car->read(disk_car,1, &buffer_org, current_pos)) return 1; memset(buffer,0,SECTOR_SIZE); memcpy(buffer,buffer_org,TAB_PART); buffer[0x1FE]=0x55; buffer[0x1FF]=0xAA; if(ro) { if(debug>1) diff(buffer,buffer_org); } else { if(disk_car->write(disk_car,1, &buffer, current_pos)) { ecrit_rapport(msg_PART_WR_ERR); display_message(msg_PART_WR_ERR); } } } else { for(element=pos_ext->next;(element!=NULL) && (element->part->status==STATUS_LOG);element=element->next) { int j; unsigned char buffer[SECTOR_SIZE]; unsigned char buffer_org[SECTOR_SIZE]; if(debug) { ecrit_rapport("write_all_log: CHS: %u/%u/%u,lba=%lu\n", LBA2cylinder(disk_car,current_pos), LBA2head(disk_car,current_pos), LBA2sector(disk_car,current_pos),current_pos); } if(disk_car->read(disk_car,1, &buffer_org, current_pos)) return 1; memset(buffer,0,SECTOR_SIZE); memcpy(buffer,buffer_org,TAB_PART); buffer[0x1FE]=0x55; buffer[0x1FF]=0xAA; partition2entry(disk_car,current_pos,element->part, pt_offset(buffer,0)); if(element->next!=NULL && (element->next->part->status==STATUS_LOG)) { /* Construit le pointeur vers la prochaine partition logique */ t_CHS nextext_start; LBA2CHS(disk_car,element->next->part->lba,&nextext_start); nextext_start.head=0; nextext_start.sector=1; bloc_nextext->lba=CHS2LBA(disk_car,&nextext_start); /* ecrit_rapport("table[i]->next=%p table[i+1]=%p\n",table[i]->next,table[i+1]); */ bloc_nextext->part_size=(element->next->part->lba+element->next->part->part_size-1)-bloc_nextext->lba+1; partition2entry(disk_car,pos_ext->part->lba,bloc_nextext, pt_offset(buffer,1)); } if(ro) { if(debug>1) { for(j=0;j<4;j++) { const struct partition_dos *p=pt_offset(buffer,j); if(p->sys_ind!=0) aff_entry_rapport(p); } diff(buffer,buffer_org); } } else { if(disk_car->write(disk_car,1, &buffer, current_pos)) { ecrit_rapport(msg_PART_WR_ERR); display_message(msg_PART_WR_ERR); } } current_pos=bloc_nextext->lba; } } FREE(bloc_nextext); return 0; } static t_list_part *do_recover_cih(t_param_disk *disk_car,t_list_part *list_part,int debug,const int dump_ind) { /* tab_part need to be sorted */ if((list_part==NULL) || (LBA2cylinder(disk_car,list_part->part->lba)>0)) { t_CHS start,end; t_diskext *partition; start.cylinder=0; start.head=1; start.sector=1; dup_t_CHS(&end,&disk_car->CHS); if(list_part!=NULL) { end.cylinder=LBA2cylinder(disk_car,list_part->part->lba)-1; } partition=partition_new(); partition->lba=CHS2LBA(disk_car,&start); partition->part_size=CHS2LBA(disk_car,&end)-partition->lba+1; if(rebuild_FAT_BS(disk_car,partition,debug,dump_ind,1)==0) { ecrit_rapport("rebuild_FAT_BS Ok\n"); return insert_new_partition(list_part,partition); } else FREE(partition); } { t_diskext *partition; t_list_part *element; t_list_part *last=NULL; for(element=list_part;element!=NULL;element=element->next) last=element; if(last!=NULL) { partition=partition_new(); partition->lba=last->part->lba+last->part->part_size-1; partition->part_size=disk_car->size-partition->lba+1; if(rebuild_FAT_BS(disk_car,partition,debug,dump_ind,1)==0) { ecrit_rapport("rebuild_FAT_BS Ok\n"); return insert_new_partition(list_part,partition); } else FREE(partition); } } return list_part; } int interface_recovery(t_param_disk *disk_car,int paranoid,const int debug,const int dump_ind, int fast_mode,int align, const int recover_cih,const int ask_part_order, const int max_ext) { int res_interface_write; do { t_list_part *list_part; t_list_part *element; int can_search_deeper=1; aff_copy(stdscr); wmove(stdscr,4,0); wdoprintf(stdscr,"%s",disk_car->description(disk_car)); wmove(stdscr,5,0); res_interface_write=0; if(paranoid==1 && fast_mode==2) can_search_deeper=0; list_part=search_part(disk_car,paranoid,debug,dump_ind,fast_mode,1); if(align) align_structure(disk_car,list_part); /* Little trick to detect Linux software Raid 1 quickly */ for(element=list_part;element!=NULL;element=element->next) { unsigned char buffer[8*SECTOR_SIZE]; struct mdp_superblock_s *sb=(struct mdp_superblock_s*)&buffer; dword offset=MD_NEW_SIZE_SECTORS(element->part->part_size); if(disk_car->read(disk_car,8, &buffer, element->part->lba+offset)==0) { t_diskext *new_partition=partition_new(); dup_t_diskext(new_partition,element->part); if(test_MD(disk_car,sb,new_partition,debug,dump_ind)==0) { set_MD_info(disk_car,sb,new_partition,debug,dump_ind); new_partition->part_type=P_RAID; new_partition->part_size=(sb->size<<1)+MD_RESERVED_SECTORS; list_part=insert_new_partition(list_part,new_partition); } else FREE(new_partition); } } if(align) /* Need to align new partition */ align_structure(disk_car,list_part); init_structure(disk_car,list_part,debug); #ifdef DEBUG check_list_part(list_part); #endif if(debug) { /* Ajoute dans le fichier de log les partitions trouvees */ ecrit_rapport("\nResults\n"); for(element=list_part;element!=NULL;element=element->next) aff_part_rapport(disk_car,element->part); } wdoprintf(stdscr,msg_GOD_MODE); list_part=ask_structure(disk_car,list_part,debug); if(test_structure(list_part)==0) { list_part=reduce_structure(list_part); #ifdef DEBUG check_list_part(list_part); #endif /* Sort list_part */ list_part=sort_list_part(list_part); #ifdef DEBUG check_list_part(list_part); #endif if(recover_cih) { list_part=do_recover_cih(disk_car,list_part,debug,dump_ind); list_part=sort_list_part(list_part); } /* Creer la partition etendue globale */ list_part=add_ext_part(disk_car,list_part,max_ext); /* ecrit_rapport("\nResults with extended\n"); for(element=list_part;element;element=element->next) aff_part_rapport(disk_car,element->part); */ init_part_order(list_part); if(ask_part_order) { /* Demande l'ordre des entrees dans le MBR */ ask_mbr_order(disk_car,list_part); /* Demande l'ordre des partitions etendues */ } res_interface_write=interface_write(disk_car,list_part,can_search_deeper); switch(res_interface_write) { case 1: if(ask_confirmation("Write partition table, confirm ? (Y/N)")) { ecrit_rapport("write!\n"); write_mbr(disk_car,list_part,RW,debug); write_all_log(disk_car,list_part,RW,debug); use_backup(disk_car,list_part,debug,dump_ind); } else ecrit_rapport("Don't write, no confirmation\n"); break; case 0: ecrit_rapport("simulate write!\n"); write_mbr(disk_car,list_part,RO,debug); write_all_log(disk_car,list_part,RO,debug); break; case 2: paranoid=1; if(fast_mode<2) fast_mode++; break; } } delete_list_part(list_part); } while(res_interface_write==2); return 0; }